import _ from 'lodash'
import { resolveComponent, type Ref, h } from 'vue'
import { type Store } from 'vuex'
import { objectFrom, switchValue } from '../../tools'

const costItemPropsBuild = () => ({
  component: 'cost-item',
  inject: 'context.data.items.value'
})

export const roleMapping = [
  ['id', { hidden: true, type: Number }],
  ['name', String, '角色名称'],
  ['marks', { 'column-hidden': true, type: String }, '备注'],
  ['head_path', { type: 'ImageSelect', inject: 'context.data.images.value' }, '角色头像'],
  ['cost', { 'column-hidden': true, ...costItemPropsBuild() }, '花费'],
  [
    'parameter',
    {
      'column-hidden': true,
      component: 'role-parameter',
      option: 'roleParameter'
    },
    '角色参数'
  ],
  ['description', { autosize: { minRows: 3, maxRows: 6 }, type: 'textarea' }, '角色描述'],
  [
    'skills',
    { 'column-hidden': true, type: 'Checklist', inject: 'context.data.skills.value' },
    '角色技能'
  ],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

export const scriptMapping = [
  ['id', { hidden: true, type: Number }],
  ['name', String, '脚本名称'],
  ['type', { type: 'Select', option: 'scriptType' }, '触发类型'],
  [
    'event',
    {
      'column-hidden': true,
      type: 'Select',
      inject: 'context.data.scriptEvents.value',
      component: 'script-event'
    },
    '触发事件'
  ],
  [
    'condition',
    {
      'column-hidden': true,
      inject: 'context.data.scriptCondition.value',
      component: 'script-condition'
    },
    '触发条件'
  ],
  [
    'actions',
    {
      'column-hidden': true,
      inject: 'context.data.scriptActions.value',
      component: 'script-action'
    },
    '触发动作'
  ], // 准备施法，消耗资源，施法中，施法结束等
  ['description', { autosize: { minRows: 3, maxRows: 6 }, type: 'textarea' }, '脚本描述'],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

export const skillMapping = [
  ['id', { hidden: true, type: Number }],
  ['name', String, '技能名称'],
  ['marks', { 'column-hidden': true, type: String }, '备注'],
  ['head_path', { type: 'ImageSelect', inject: 'context.data.images.value' }, '技能头像'],
  [
    'parameter',
    {
      'column-hidden': true,
      component: 'skill-parameter',
      option: 'skillParameter'
    },
    '技能参数'
  ],
  ['target_type', { type: 'Select', option: 'skillTargetType' }, '技能目标类型'],
  ['target_allowed', { type: 'Checkbox', option: 'skillTargetAllowed' }, '技能目标允许'],
  [
    'scripts',
    { 'column-hidden': true, type: 'Checklist', inject: 'context.data.scripts.value' },
    '执行脚本'
  ],
  ['description', { autosize: { minRows: 3, maxRows: 6 }, type: 'textarea' }, '技能描述'],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

export const missionMapping = [
  ['id', { hidden: true, type: Number }],
  ['name', String, '关卡名称'],
  ['marks', { 'column-hidden': true, type: String }, '备注'],
  [
    'scripts',
    { 'column-hidden': true, type: 'Checklist', inject: 'context.data.scripts.value' },
    '执行脚本'
  ],
  ['mission_check', { 'edit-hidden': true, type: 'Select', option: 'missionCheck' }, '校验'],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

export const instanceMapping = [
  ['id', { hidden: true, type: Number }],
  ['name', String, '副本名称'],
  ['head_path', { type: 'ImageSelect', inject: 'context.data.images.value' }, '副本背景'],
  ['award', { 'column-hidden': true, ...costItemPropsBuild() }, '副本奖励'],
  [
    'mission_ids',
    { 'column-hidden': true, type: 'Checklist', inject: 'context.data.missions.value' },
    '关卡顺序'
  ],
  ['instance_check', { 'edit-hidden': true, type: 'Select', option: 'instanceCheck' }, '校验'],
  ['description', { autosize: { minRows: 3, maxRows: 6 }, type: 'textarea' }, '副本描述'],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

const materialTypeChange = (form: any) => {
  const pathMapping = ['role', 'item', 'skill', 'instance']
  return (value: any) => {
    const materialKey = 'material-seed'
    let seed = Number(localStorage.getItem(materialKey))
    if (!(seed >= 0)) {
      seed = 0
    }
    form.value.path = `/${pathMapping[value]}/a${seed}`
  }
}

export const materialMapping = [
  ['id', { hidden: true, type: Number }],
  ['path', String, '素材地址'],

  ['type', { type: 'Select', option: 'materialType', change: materialTypeChange }, '素材类型'],
  ['ratio', { type: 'Select', option: 'materialRatio' }, '素材宽高比'],
  [
    'data',
    {
      // "column-hidden": true,
      type: 'ImageEdit',
      inject: ['formData.value.ratio', 'ratio']
    },
    '素材内容'
  ],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

export const itemMapping = [
  ['id', { hidden: true, type: Number }],
  ['name', String, '物品名称'],
  ['marks', { 'column-hidden': true, type: String }, '备注'],
  ['head_path', { type: 'ImageSelect', inject: 'context.data.images.value' }, '物品头像'],
  ['cost', { 'column-hidden': true, ...costItemPropsBuild() }, '花费'],
  [
    'skills',
    { 'column-hidden': true, type: 'Checklist', inject: 'context.data.skills.value' },
    '物品技能'
  ],
  ['description', { autosize: { minRows: 3, maxRows: 6 }, type: 'textarea' }, '物品描述'],
  ['create_time', { 'edit-hidden': true, type: String }, '创建时间']
]

export const buildFields = (type: string) => {
  const toFields = (list: any) => {
    return list
  }

  if (type === 'script') {
    return toFields(scriptMapping)
  }

  if (type === 'skill') {
    return toFields(skillMapping)
  }

  if (type === 'role') {
    return toFields(roleMapping)
  }

  if (type === 'mission') {
    return toFields(missionMapping)
  }

  if (type === 'instance') {
    return toFields(instanceMapping)
  }

  if (type === 'material') {
    return toFields(materialMapping)
  }

  if (type === 'item') {
    return toFields(itemMapping)
  }

  return []
}

export const buildColumns = (type: string, room: { context: any; store: Store<any> }) => {
  const optionsFactory = (mapping: any, optionName: string) => {
    const inject = mapping.get('inject')
    if (inject) {
      if (Array.isArray(inject)) {
        return _.get(room.context, inject[0])
      } else {
        return _.get(room.context, inject)
      }
    } else {
      const options = _.get(room.store, `state.options[${optionName}]`)
      if (options) {
        return Array.from(options)
      }
    }
    return []
  }

  const toColumns = (list: Array<any>) => {
    const columns: Array<any> = []
    if (Array.isArray(list)) {
      list.forEach((row) => {
        if (Array.isArray(row)) {
          const [prop, option, label] = row
          let type: any = String
          let hidden = false
          const mapping = new Map()
          if (typeof option === 'object') {
            type = option.type
            if (option.hidden || option['edit-hidden']) {
              hidden = true
            }
            Object.keys(option).forEach((key) => mapping.set(key, option[key]))
          } else {
            type = option
          }
          if (typeof option === 'object') {
            // type = option.type
            if (option['hidden'] || option['column-hidden']) {
              hidden = true
            }
          }
          if (!hidden) {
            const column: any = {
              label,
              prop,
              width: 200,
              render: undefined
            }

            if (type === 'Select') {
              const list = optionsFactory(mapping, option.option)
              let key = 'id',
                value = 'name'
              const keyValue = mapping.get('keyValue')
              if (Array.isArray(keyValue)) {
                key = keyValue[0]
                value = keyValue[1]
              }
              column.render = (data: string) => switchValue(data, list, key)[value]
            }

            if (type === 'ImageSelect') {
              column.render = (data: string) =>
                h(resolveComponent('cg-image'), { path: data, style: { height: '40px' } })
            }

            if (type === 'ImageEdit') {
              column.render = (data: string, row: any) =>
                h(resolveComponent('cg-image'), { path: row['path'], style: { height: '40px' } })
            }

            columns.push(column)
          }
        }
      })
    }
    return columns
  }

  if (type === 'script') {
    return toColumns(scriptMapping)
  }

  if (type === 'skill') {
    return toColumns(skillMapping)
  }

  if (type === 'role') {
    return toColumns(roleMapping)
  }

  if (type === 'mission') {
    return toColumns(scriptMapping)
  }

  if (type === 'instance') {
    return toColumns(instanceMapping)
  }

  if (type === 'material') {
    return toColumns(materialMapping)
  }

  if (type === 'item') {
    return toColumns(itemMapping)
  }

  return []
}

export const buildEditFields = (
  type: string,
  room: { context: any; formData: Ref; store: Store<any> }
) => {
  const injectFactory = (mapping: any, field: any) => {
    const injects = mapping.get('injects')
    if (Array.isArray(injects)) {
      injects.forEach((inject) => {
        if (Array.isArray(inject)) {
          field.props[inject[1]] = _.get(room, inject[0])
        }
      })
      return true
    }

    const defaultInjectPropName = 'options'
    const inject = mapping.get('inject')
    if (inject) {
      if (Array.isArray(inject)) {
        field.props[inject[1]] = _.get(room, inject[0])
      } else {
        field.props[defaultInjectPropName] = _.get(room, inject)
      }
      return true
    }
  }

  const optionFactory = (data: any, field: any) => {
    const options = _.get(room.store, `state.options[${data[0]}]`)
    if (options) {
      field.props[data[1]] = Array.from(options)
    }
  }

  const toFields = (list: Array<any>) => {
    const fields: any = []
    if (Array.isArray(list)) {
      list.forEach((row) => {
        if (Array.isArray(row)) {
          const [id, option, label] = row
          let type: any = String
          let hidden = false
          const mapping = new Map()
          if (typeof option === 'object') {
            type = option.type
            if (option.hidden || option['edit-hidden']) {
              hidden = true
            }
            Object.keys(option).forEach((key) => mapping.set(key, option[key]))
          } else {
            type = option
          }
          if (!hidden) {
            const field: any = {
              id,
              label,
              props: {},
              component: undefined,
              on: undefined
            }
            const component = mapping.get('component')

            if (component) {
              field.component =
                _.get(room, `context.components.${_.camelCase(component)}`) ||
                resolveComponent(component)
              injectFactory(mapping, field)
              optionFactory([option.option, 'options'], field)
            } else if (type !== String) {
              if (type === Number) {
                field.component = 'cg-input-number'
              }
              if (type === 'Select' || type === 'MultipleSelect') {
                field.component = 'cg-select'
                if (type === 'MultipleSelect') {
                  field.component = 'cg-multiple-select'
                }
                injectFactory(mapping, field)
                optionFactory([option.option, 'options'], field)
                const changeFactory = mapping.get('change')
                if (typeof changeFactory === 'function') {
                  field.on = { change: changeFactory(room.formData) }
                }
              }

              if (type === 'textarea') {
                field.props['type'] = 'textarea'
                const autosize = mapping.get('autosize')
                if (autosize) {
                  field.props['autosize'] = autosize
                }
              }

              if (type === 'Checkbox') {
                field.component = 'cg-checkbox'
                optionFactory([option.option, 'options'], field)
              }

              if (type === 'Checklist') {
                field.component = 'cg-checklist'
                injectFactory(mapping, field)
              }

              if (type === 'ImageEdit') {
                field.component = 'cg-image-edit'
                injectFactory(mapping, field)
              }

              if (type === 'ImageSelect') {
                field.component = 'cg-image-select'
                injectFactory(mapping, field)
              }
            }
            fields.push(field)
          }
        }
      })
    }

    return fields
  }

  const mapping: any = {
    script: scriptMapping,
    skill: skillMapping,
    role: roleMapping,
    mission: missionMapping,
    instance: instanceMapping,
    material: materialMapping,
    item: itemMapping
  }

  return toFields(mapping[type])
}

export const buildEmptyForm = (type: any) => {
  const toForm = (list: any) => {
    const form: any = {}
    if (Array.isArray(list)) {
      list.forEach((row) => {
        if (Array.isArray(row)) {
          const [prop, option] = row
          if (typeof option === 'object') {
            type = option.type
          }
          if (type === String) {
            form[prop] = ''
          } else {
            form[prop] = undefined
          }
        }
      })
    }
    return (item?: any) => {
      return objectFrom(form, item)
    }
  }

  const mapping: any = {
    script: scriptMapping,
    skill: skillMapping,
    role: roleMapping,
    mission: missionMapping,
    instance: instanceMapping,
    material: materialMapping,
    item: itemMapping
  }

  return toForm(mapping[type])
}
